﻿using System;
using System.Collections;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Tabs;
using DotNetNuke.Entities.Users;
using DotNetNuke.Security;
using DotNetNuke.Security.Permissions;

namespace BigfootMVC.DNN
{

    /// <summary>
    /// This class represents the route information. It includes controller, action, portalid, tabid, and moduleid
    /// This info is by default created from the url in the route parameter.
    /// </summary>
    public class RouteInfo
    {

        /// <summary>
        /// Empty constructor. All data must be specified in order for the application to work properly
        /// </summary>
        public RouteInfo() { }

        /// <summary>
        /// Creates a new RouteInfo object by specifying. Defaults the Controller and Action to the default values
        /// </summary>
        public RouteInfo(PortalModuleBase module, int portalId, DnnApp app)
        {
            Controller = "Home";
            Action = "Index";
            Module = module;
            PortalId = portalId;
            App = app;
        }

        /// <summary>
        /// Creates a new RouteInfo object by specifying the full range of parameters
        /// </summary>
        public RouteInfo(string controller, string action, PortalModuleBase module, int portalId, DnnApp app)
        {
            Controller = controller;
            Action = action;
            Module = module;
            PortalId = portalId;
            App = app;
        }

        /// <summary>
        /// Name of the controller for this route
        /// </summary>
        public string Controller;

        /// <summary>
        /// Name of the action within the controller
        /// </summary>
        public string Action;
        
        /// <summary>
        /// This is the module configuration for the PortalModuleBase under which context we are executing
        /// </summary>
        public PortalModuleBase Module { get; set; }

       
       
        #region "Module Settings"

        

        /// <summary>
        /// Retreives a module setting as an integer
        /// </summary>
        /// <param name="name">The name of the setting to retreive</param>
        public int? GetSettingAsInt(string name)
        {
            return GetSetting(name) != "" ? int.Parse(GetSetting(name))
                                          : new int?();
        }

        /// <summary>
        /// Retreives a module setting as an integer
        /// </summary>
        /// <param name="name">The name of the setting to retreive</param>
        /// <param name="defaultValue">Uses this default value if nothing is found</param>
        public int GetSettingAsInt(string name, int defaultValue)
        {
            return int.Parse(GetSetting(name, defaultValue.ToString()));
        }

        /// <summary>
        /// Retreives a module setting as a date
        /// </summary>
        /// <param name="name">The name of the setting to retreive</param>
        public DateTime? GetSettingAsDate(string name)
        {
            return GetSetting(name) != "" ? DateTime.Parse(GetSetting(name))
                                          : new DateTime();
        }

        /// <summary>
        /// Retreives a module setting as a date
        /// </summary>
        /// <param name="name">The name of the setting to retreive</param>
        /// <param name="defaultValue">Uses this as the default value if nothing is found</param>
        public DateTime GetSettingAsDate(string name, DateTime defaultValue)
        {
            return DateTime.Parse(GetSetting(name, defaultValue.ToString()));
        }

        /// <summary>
        /// Retreives a module setting as a decimal
        /// </summary>
        /// <param name="name">The name of the setting to retreive</param>
        public decimal? GetSettingAsDecimal(string name)
        {
            return GetSetting(name) != "" ? decimal.Parse(GetSetting(name))
                                          : new decimal?();
        }

        /// <summary>
        /// Retreives a module setting as a decimal
        /// </summary>
        /// <param name="name">The name of the setting to retreive</param>
        /// <param name="defaultValue">Uses this as the default value if the setting is not found</param>
        public decimal GetSettingAsDecimal(string name, decimal defaultValue)
        {
            return decimal.Parse(GetSetting(name, defaultValue.ToString()));
        }

        /// <summary>
        /// Retreives a module setting as a string
        /// </summary>
        /// <param name="name">The name of the setting to retreive</param>
        /// <returns>Returns an empty string if not found</returns>
        public string GetSetting(string name)
        {
            return GetSetting(name, "");
        }

        /// <summary>
        /// Retreives a module setting as a string
        /// </summary>
        /// <param name="name">The name of the setting to retreive</param>
        /// <param name="defaultValue">Uses this as the default value if the setting is not found</param>
        public string GetSetting(string name, string defaultValue)
        {
            return string.IsNullOrEmpty((string)Module.Settings[name]) == false ? (string)Module.Settings[name] : defaultValue;
        }

        #endregion

        
        /// <summary>
        /// Determines wheather the current user has edit rights to this module. It does not use the IsEditable as that would not work in ajax scenarios
        /// instead it goes directly to the tab info and identify if the tab has or module has edit rights
        /// </summary>
        public bool CanEdit
        {
            get
            {
                if (canEdit.HasValue == false)
                {
                    //var tabPermissions = (new TabController()).GetTab(TabId, PortalId, false).TabPermissions;
                    canEdit = //TabPermissionController.HasTabPermission(tabPermissions, "EDIT") || 
                              ModulePermissionController.HasModulePermission(Module.ModuleConfiguration.ModulePermissions, "EDIT");
                }
                return canEdit.Value;
            }
        }
        private bool? canEdit;

        /// <summary>
        /// Portal ID for this request
        /// </summary>
        public int PortalId { get; set; }

        /// <summary>
        /// TabId for this request
        /// </summary>
        public int TabId { get{ return Module.TabId; } }

        /// <summary>
        /// ModuleId for this request
        /// </summary>
        public int ModuleId { get{ return Module.ModuleId; } }
        
        /// <summary>
        /// Carries the user information for the current request
        /// </summary>
        public UserInfo User { get; set; }

        /// <summary>
        /// Returns the user id of the currently logged in user. Throws an error if the user is not logged in
        /// </summary>
        public int UserId { get
        {
            if (User == null)
                throw new ApplicationException("No user has has been attached to this process");
            return User.UserID;
        } }

        /// <summary>
        /// Returns the user id of the currently logged in user or a default value you specify
        /// </summary>
        public int UserIdOrDefault(int defaultValue)
        {
            return (User == null) ? defaultValue : User.UserID;
        }

        /// <summary>
        /// Determines if the user is admin
        /// </summary>
        public bool UserIsAdmin { get {return  (User == null || 
                                                User.IsSuperUser || 
                                                User.IsInRole("Administrators")); } }

        /// <summary>
        /// Determines if the user is a host user
        /// </summary>
        public bool UserIsHost { get { return (User == null || User.IsSuperUser); } }

        /// <summary>
        /// Creates a properly formatted url with the route parameter built from this RouteInfo object
        /// </summary>
        /// <returns>A url that can be used from the client</returns>
        public string GetMvcUrl()
        {
            // Add all query string parameters that are not routes. Other routes are automatically appended by the 
            // App.BuildUrlRoute function
            var querystring = "";
            foreach (string key in App.Request.QueryString.Keys)
            {
                if (key.ToLowerInvariant().StartsWith("route_")) continue;
                querystring += "&" + key + "=" + App.Request.QueryString[key];
            }
            return Url.MvcUrl(Controller, Action, querystring);            
        }

        /// <summary>
        /// Creates a properly formatted url with the route parameter built from this RouteInfo object
        /// </summary>
        /// <returns>A url that can be used from the client</returns>
        public string GetMvcAjaxUrl()
        {
            var querystring = "";
            foreach (string key in App.Request.QueryString.Keys)
            {
                if (key == Params.QS.AjaxRoute(App.ModuleShortName)) continue;
                querystring += "&" + key + "=" + App.Request.QueryString[key];
            }
            return Url.MvcAjaxUrl(Controller, Action, querystring);
        }

        /// <summary>
        /// Returns the path to the view based on the controller and action
        /// i.e. controller=home, action=index then the view path returned would be ~/desktopmodules/modulename/views/controller/action.ascx
        /// </summary>
        /// <returns>A relative url ~/desktopmodules/modulename/views/controller/action.ascx</returns>
        public string ViewPath
        {
            get { return RouteHelper.ControlPath(Controller, Action, App); }
        }
        
        /// <summary>
        /// Creates a new instance of the UrlHelper class to help you create urls
        /// </summary>
        public UrlHelper Url
        {
            get { return _url ?? (_url = new UrlHelper(this)); }
        }
        private UrlHelper _url;

        /// <summary>
        /// This is the heart of your DNN module application. It contains your module informaiton, as well as the methods
        /// and helpers you may use throughout your application. It also is the main source for the StaticUrl MvcUrl and ControlUrl
        /// methods that the baseview classes inherit. It also has all the functions inherited from the BigfootMVC.WebApp 
        /// you may use in all ASP.NET applications.
        /// </summary>
        public DnnApp App { get; set; }
    }

}
